package com.guojian.jdbc.mapper;

import java.util.Map;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import org.springframework.util.Assert;

import com.guojian.jdbc.JdbcDataFormat;

/**
 * 
 * 
 * 
 * @author GuoJian
 *
 */
public class RowMapperTemplate<T> {

	public static class RowMapperTemplateBuilder<T> {

		private boolean isAddLowerCaseOfName = false;

		private Class<T> mapperClass;

		/*private JdbcDataFormat<T> dataFormat;*/

		public RowMapperTemplateBuilder() {
		}

		public RowMapperTemplateBuilder(Class<T> mapperClass) {
			this.mapperClass = mapperClass;
		}

		public boolean isAddLowerCaseOfName() {
			return isAddLowerCaseOfName;
		}

		public RowMapperTemplateBuilder<T> setAddLowerCaseOfName(boolean isAddLowerCaseOfName) {
			this.isAddLowerCaseOfName = isAddLowerCaseOfName;
			return this;
		}

		public RowMapper<Map<String, String>> createStringMapRowMapper(JdbcDataFormat<Map<String, String>> format) {
			StringMapRowMapper stringMapRowMapper = new StringMapRowMapper(this.isAddLowerCaseOfName);
			if (format != null) {
				return new DataFormatRowMapper<>(format, stringMapRowMapper);
			}
			return stringMapRowMapper;
		}

		public RowMapper<Map<String, Object>> createObjectMapRowMapper(JdbcDataFormat<Map<String, Object>> format) {
			ObjectMapRowMapper objectMapRowMapper = new ObjectMapRowMapper(this.isAddLowerCaseOfName);
			if (format != null) {
				return new DataFormatRowMapper<>(format, objectMapRowMapper);
			}
			return objectMapRowMapper;
		}

		public RowMapper<Map<String, T>> createMapRowMapper(JdbcDataFormat<Map<String, T>> format) {
			RowMapper<Map<String, T>> mapRowMapper = this.mapperClass == null ? new MapRowMapper<>(this.isAddLowerCaseOfName) : new MapRowMapper<>(this.mapperClass, this.isAddLowerCaseOfName);
			if (format != null) {
				return new DataFormatRowMapper<>(format, mapRowMapper);
			}
			return mapRowMapper;
		}

		/**
		 * 单列的值,如果查询的结果有多列,则取第一列的值
		 * @param format
		 * @return
		 */
		public RowMapper<T> createSingleColumnRowMapper(JdbcDataFormat<T> format) {
			Assert.notNull(this.mapperClass, "MapperClass must not be null");
			SingleColumnRowMapper<T> singleColumnRowMapper = new SingleColumnRowMapperOfPage<>(this.mapperClass);
			if (format != null) {
				return new DataFormatRowMapper<>(format, singleColumnRowMapper);
			}
			return singleColumnRowMapper;
		}

		/**
		 * 数据库的值自动映射到实体,[1.不区分大小写 2.大写转下划线 bean[beginDate]->begin_date]
		 * @param format
		 * @return
		 */
		public RowMapper<T> createBeanPropertyRowMapper(JdbcDataFormat<T> format) {
			Assert.notNull(this.mapperClass, "MapperClass must not be null");
			BeanPropertyRowMapper<T> beanRowMapper = new BeanPropertyRowMapper<>(this.mapperClass);
			if (format != null) {
				return new DataFormatRowMapper<>(format, beanRowMapper);
			}
			return beanRowMapper;
		}

	}

	public static <T> RowMapperTemplateBuilder<T> builder() {
		return new RowMapperTemplate.RowMapperTemplateBuilder<T>();
	}

	public static <T> RowMapperTemplateBuilder<T> builder(Class<T> c) {
		return new RowMapperTemplate.RowMapperTemplateBuilder<T>(c);
	}

	public static <T> RowMapper<Map<String, T>> getMapRowMapper(Class<T> mapperClass, boolean isAddLowerCaseOfName, JdbcDataFormat<Map<String, T>> format) {
		return RowMapperTemplate.builder(mapperClass).setAddLowerCaseOfName(isAddLowerCaseOfName).createMapRowMapper(format);
	}

	public static <T> RowMapper<T> getSingleColumnRowMapper(Class<T> mapperClass, boolean isAddLowerCaseOfName, JdbcDataFormat<T> format) {
		return RowMapperTemplate.builder(mapperClass).setAddLowerCaseOfName(isAddLowerCaseOfName).createSingleColumnRowMapper(format);
	}

	public static <T> RowMapper<T> getBeanRowMapper(Class<T> mapperClass, JdbcDataFormat<T> format) {
		return RowMapperTemplate.builder(mapperClass).createBeanPropertyRowMapper(format);
	}

	public static void main(String[] args) {
		/*TypeToken<Map<String, Object>> token = new TypeToken<Map<String, Object>>() {
		};
		TypeToken<Map<String, String>> token1 = new TypeToken<Map<String, String>>() {
		};*/
	}

}
